iT邦幫忙

2026 iThome 鐵人賽

DAY 21
0
AI Engineering

一天一個 PR,讓我告訴你嵌入式開發的殘酷:如何為 AI Agent 建立可信的工程閉環系列 第 21

Day 21 - 工單都寫好了,Workflow 卻還不想動:Coordinator推著它走

  • 分享至 

  • xImage
  •  

系列說明 >> 本系列大部分 PR 來自私人或公司專案,部分程式碼、環境設定與實作細節不便公開。

我只能保證文中提到的 PR 與問題皆為真實案例,但會經過必要的匿名化與內容調整。

本系列主要分享問題如何被發現、背後的思考方式,以及解法如何形成,不會深入討論完整實作與部署細節,敬請見諒。

Today’s Change

  • Base Repo: paulsha-cortex

  • Change Ref: PR #1-feat: bootstrap paulsha-cortex 治理平面拆包

  • Issue: Deck 已經能把 Card/Combo 編成 dispatch: hold 的 Slice Specs,但誰判斷 Ready、誰 Dispatch、誰接住 Completion、誰把下一段放出去,以及 Operator 要怎麼送出 Retry/Pause/Resume,仍混在 paulshaclaw 的 Manager 與操作路徑裡。讀者看得到工作單,Runtime Responsibility 卻還沒有清楚分層。

  • Root Cause: 「工作怎麼定義」、「工作怎麼往下走」與「人怎麼介入」被放在同一個 Repo、同一組路徑與共用 Helper 裡。Coordinator/Control 的責任雖然已經存在,卻沒有獨立的 Runtime Boundary;只 Copy Source,Path、Phase/Idle、CLI、Service 與舊 memory 模組依賴仍會把新 Repo 拉回舊環境。

  • Solution: 先把 Coordinator 與 Control 的責任切清楚:Coordinator 掃描 Specs、判 Ready、Dispatch、接 Completion/Handoff 並 Release 下游;Control 提供 Operator Request/Runtime Status 的正式交換面。接著建立 paulsha-cortex,平移 persona / coordinator / control,補齊自己的 Path Contract、Phase/Idle 定義、CLI、Hooks、Service/Installer 與受限 Runtime Config Parser,剪除對舊 memory 模組提供之基本 Runtime 定義的直接依賴。

  • Evidence: PR #1 完成 Tests、Policy Check、去識別化掃描與 Fresh-install Smoke;pip install .cortex --help Exit 0,核心執行對舊 memory Namespace 的直接依賴清零。這些證據支持 Persona/Coordinator/Control 已形成可獨立安裝與啟動的 Runtime Nucleus;完整 Package Cutover 與舊 Manager 退役仍留待下一步。


五份工作單排得很整齊,然後大家一起不動

上一篇,Deck 把 feature-oneshot 編成五份 Specs。

build                    dispatch: hold
code-review              dispatch: hold
verification             dispatch: hold
ship                     dispatch: hold
adversarial-review       dispatch: hold

Dependency 也寫好了。

Build 沒完成,Review 不該開始;Review 沒完成,Verification 先等著。

很好。

這次總算不用我站在十個小bu旁邊,一個一個提醒下一步。

小bu看著五份工作單。

「都生出來了,我先把 hold 全改成 auto?」

我差點答應。

反正 Dependency 已經寫在裡面,先全部放出去,該等的自然會等。

小ma抬頭。

「還沒。」

「又怎麼了?」

「誰確認上游真的完成?」

「誰接它交回來的 Artifact?」

「誰決定下一份現在可以放?」

小bu覺得這些都是小事。

「我可以在每份 Spec 後面補一個 Script。」

小re接得很快:

「那五份工作,是不是就要各自長出一小段 Manager?」

……好。

牌是寫好了。

但牌不會自己知道現在輪到哪一張。

Target

前幾天一直說「還沒」的小ma,回到 Source 裡叫 Coordinator

前幾天,我們一路補過:

poll
→ gate
→ handoff
→ release downstream

故事裡的小ma,偏見一直很單純:

單一步驟做完,不代表整個 Lifecycle 可以往下。

但小ma不是 Source Tree 裡的一個 Package。

回到 Code,真正會掃描 Specs、計算 Ready Unit、Dispatch Worker、接住 Completion,再把下游放出去的,是 coordinator

為了確認我沒有又把一個名詞想得太玄,我乾脆手動演了一次。

先把 Build 翻成 auto

等它完成。

看 Handoff。

再去把 Review 放出去。

接著等 Review。

再放 Verification。

做到第三張時,老Go問:

「你現在是在驗證 Coordinator,還是親自應徵 Coordinator?」

我看著手上的終端機。

確實。

Deck 幫我省掉了手寫五份工作單。

我卻又把自己補回去,負責逐張看、逐張放、逐張收。

所以 Coordinator 的責任不是「另一個會寫 Code 的 Agent」。

它是在工作已經被定義之後,持續回答:

現在誰 Ready?
誰還得等?
完成的 Artifact 在哪裡?
下一個 Transition 能不能發生?

小pa聽到這裡,順手把界線補了一刀:

「Plan 已經告訴你這次要做什麼。」

「不要每次 Runtime 卡住,又回來叫 Planner 重寫一份 Plan。」

嗯。

角色終於開始各做各的事了。


Coordinator 會推進工作,但人要怎麼叫它停、重試,或先別動?

Coordinator 開始像樣之後,我又碰到另一個很現場的問題。

假設 Verification 卡住,我想:

  • 暫停這個 Job。

  • Retry 一次。

  • 改成人工接手。

  • 回答一個 Blocking Decision。

我第一個反應,是直接改 Spec 或 Status File。

小bu覺得很合理。

「反正都是 YAML/JSON,改完就生效。」

小re看了一眼:

「你現在改的是工作定義,還是在下操作命令?」

「……操作命令。」

「那為什麼寫回工作定義?」

如果我為了 Retry,直接去改 Deck 生出的 Spec,下一次就很難分辨:

這份 Workflow 本來就是這樣
還是 Operator 剛才臨時介入

反過來,如果人直接去摸 Coordinator 的 Internal State,那就更精彩了。

Coordinator 以為自己持有正式狀態。

Operator 也覺得檔案是我改的,當然算正式。

兩邊都很有 Authority。

通常只差一個晚上,就會開始互相覆蓋。

所以需要另一個邊界:Control

Operator
→ 寫 Request

Coordinator
→ 讀 Request、執行 Transition

Coordinator
→ 寫 Status

Operator
→ 讀 Status

一句話說:

Coordinator 負責讓工作往下走;Control 負責讓人跟 Runtime 對同一份 Request/Status 說話。

老Go聽完點點頭。

「方向盤可以留給人。」

「不要每次轉彎,都把手伸進齒輪箱裡撥。」

這個比喻很土。

也很難反駁。

Target


我順著 Coordinator 往下看,才發現 Shell 裡已經養出一套 Runtime

到這裡,前幾天陸續出場的責任開始對得起來了:

Persona
→ Agent 以什麼角色與 Guardrail 做事

Deck
→ 可重用工作怎麼宣告與編譯

Coordinator
→ 工作如何依 Dependency 往下走

Control
→ Operator 與 Runtime 如何交換 Request/Status

而我拿來操作這些東西的 CLI、Cockpit、Start Script,也都在 paulshaclaw。

換句話說,一邊是我伸手操作 Agent 的入口。

另一邊已經開始持有 Workflow 的正式狀態與推進責任。

兩邊都住在同一個 Repo。

小bu提出第一個方案:

「加幾條 Import Rule,把目錄分乾淨就好。」

我也很想選這條。

不用搬 Repo。

不用改 Install。

不用處理 Service。

大家各住各的資料夾,平常不要越界,看起來十分和平。

老Go問:

「你現在是靠 Boundary 讓它們分開。」

「還是靠 Test 每天提醒它們假裝分開?」

這句有點痛。

我打開 Repo Tree:

paulshaclaw/
├── persona/
├── coordinator/
├── control/
└── cli/

前三個已經是 Runtime Nucleus。

最後一個才是 Operator 入口。

所以我採用了工程師最熟悉的架構拆分方法:

cp -r paulshaclaw/persona paulsha-cortex/
cp -r paulshaclaw/coordinator paulsha-cortex/
cp -r paulshaclaw/control paulsha-cortex/

三個資料夾出現在新 Repo。

小bu宣布:

「搬完。」

小re沒有看 Git Status。

「把舊 Repo 從 PYTHONPATH 拿掉,再跑一次。」

群裡安靜了兩秒。


Source 搬過去了,Runtime 還是一直回頭拿舊家的東西

第一個撞牆的是 Hook Path。

我站在 Cortex Repo Root 手動執行,PASS。

真正從 Target Worktree 被叫起來,相對路徑立刻指到另一棵樹,Script 找不到 Runtime。

小bu抗議:

「我剛才明明跑過。」

小re問:

「你測的是 Repo Root,還是實際 Caller 的 Working Directory?」

「Repo Root。」

「那你測到的是你站的位置很正確。」

很好。

家具到了新家,地址簿還留在舊家。

接著是另一條 Dependency。

當時 paulshaclaw 裡還有一組整理 Agent 工程記憶的 memory 模組,細節後面再講。

今天只需要知道:Coordinator 要判斷 Phase、Idle 與部分 Runtime Path,竟然還得先去 Import 那組 memory Helper。

小re乾脆把它拿掉。

「現在 Cortex 還起得來嗎?」

起不來。

老Go看著 Traceback:

「記憶可以晚點載入。」

「心跳不能等記憶系統到場才開始。」

所以 PR #1 真正補的,不只是三個 Package:

自己的 Path Contract
自己的 Phase/Idle 定義
自己的 Control 基本契約
自己的 CLI、Hook、Service 與 Installer

Cortex 甚至必須能在 Target Environment 半壞、Virtualenv 不完整時讀懂自己的最低限度 Config;因此 Runtime 只內建契約真正需要的受限格式,遇到不支援內容就直接拒絕。

這時我才承認:

Source Boundary 只是檔案放哪裡。

Runtime Boundary 是拿掉舊家之後,它還知不知道自己怎麼活。

Target


cortex --help 叫得出來,只證明 Coordinator 終於有自己的門牌

最後做 Fresh-install Smoke:

pip install .
cortex --help
# exit 0

加上 Tests、Policy Check、去識別化掃描,以及對舊 memory Namespace 的直接依賴清理,這些 Evidence 可以支持:

  • Persona/Coordinator/Control 已經在 Cortex 形成可獨立安裝的 Runtime Nucleus。

  • Coordinator 有自己的 Path、Phase/Idle、CLI、Hook 與 Service 啟動面。

  • Operator 不必再透過舊 Repo,才能叫出新 Runtime。

它不能支持:

整套 Cortex 已經拆完,paulshaclaw 從此只剩 Shell。

因為還有 Runtime 能力留在舊 Repo。

更麻煩的是,舊 Manager Path 也還沒有正式退役。

我第一個想法仍然很保守:

新舊兩邊先一起留著,不是比較方便 Rollback 嗎?

小bu立刻同意。

「安全。」

小re問:

「同一份 Request,兩邊都看到時,哪一份 Status 算真的?」

小ma看了一眼舊 Timer,又看了一眼新 Service。

「還沒。」

「這次還缺什麼?」

老Go替它回答:

「你現在不是留了備份。」

「你是留了兩個人,都能踩同一台車的油門。」

下一篇,Cortex 已經能跑,舊 Manager 卻還沒下班。

Have a nice day.


上一篇
Day 20 - 明明有skill,怎麼還老是跑歪?:把skill寫成牌組 - DECK
系列文
一天一個 PR,讓我告訴你嵌入式開發的殘酷:如何為 AI Agent 建立可信的工程閉環21
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言